<template>
  <div class="flow-editor">
    <div class="toolbar">
      <el-button-group>
        <el-button @click="addNode('start')">开始节点</el-button>
        <el-button @click="addNode('process')">过程节点</el-button>
        <el-button @click="addNode('decision')">决策节点</el-button>
        <el-button @click="addNode('end')">结束节点</el-button>
        <el-button @click="mode = 'line'">连线</el-button>
        <el-button @click="clearCanvas">清空</el-button>
        <el-button @click="saveCanvas">保存</el-button>
        <el-button @click="loadCanvas">加载</el-button>
        <el-button @click="exportCanvas">导出</el-button>
        <input type="file" @change="importCanvas" style="display: none;" ref="fileInput" />
        <el-button @click="$refs.fileInput.click()">导入</el-button>
      </el-button-group>
    </div>
    <canvas
      ref="canvas"
      @mousedown="handleMouseDown"
      @mousemove="handleMouseMove"
      @mouseup="handleMouseUp"
      class="flow-canvas"
    ></canvas>
  </div>
</template>

<script setup>
import { ref, onMounted, nextTick } from 'vue'

// 画布相关
const canvas = ref(null)
const ctx = ref(null)
const mode = ref('select') // select, line
const nodes = ref([])
const lines = ref([])
const isDragging = ref(false)
const selectedNode = ref([])
const startNode = ref(null)
const scale = ref(1)

// 初始化画布
onMounted(async () => {
  await nextTick()
  const canvasEl = canvas.value
  ctx.value = canvasEl.getContext('2d')
  
  // 设置画布大小
  canvasEl.width = canvasEl.offsetWidth
  canvasEl.height = canvasEl.offsetHeight
  
  // 初始绘制
  draw()

  // 在 canvas 上添加右键菜单事件
  canvasEl.addEventListener('contextmenu', handleContextMenu)

  // 在 canvas 上添加缩放事件
  canvasEl.addEventListener('wheel', handleWheel)
})

// 绘制所有内容
const draw = () => {
  const context = ctx.value
  if (!context) return

  // 清空画布
  context.clearRect(0, 0, canvas.value.width, canvas.value.height)

  // 绘制所有节点
  nodes.value.forEach(node => {
    context.beginPath()
    switch (node.type) {
      case 'start':
        context.arc(node.x, node.y, 20, 0, Math.PI * 2) // 开始节点
        break
      case 'process':
        context.rect(node.x - 30, node.y - 15, 60, 30) // 过程节点
        break
      case 'decision':
        context.moveTo(node.x, node.y - 20);
        context.lineTo(node.x + 20, node.y);
        context.lineTo(node.x, node.y + 20);
        context.lineTo(node.x - 20, node.y);
        context.closePath(); // 决策节点
        break
      case 'end':
        context.arc(node.x, node.y, 20, 0, Math.PI * 2) // 结束节点
        break
    }
    context.fillStyle = node.color || '#fff'
    context.fill()
    context.strokeStyle = '#1890ff'
    context.stroke()

    // 绘制文本
    context.fillStyle = '#000'
    context.textAlign = 'center'
    context.textBaseline = 'middle'
    context.fillText(node.text, node.x, node.y)
  })

  // 绘制所有连线
  lines.value.forEach(line => {
    context.beginPath()
    context.moveTo(line.start.x, line.start.y)
    context.lineTo(line.end.x, line.end.y)
    context.strokeStyle = '#1890ff'
    context.lineWidth = 2; // 设置线宽
    context.stroke()

    // 添加箭头
    const headlen = 10; // 箭头长度
    const angle = Math.atan2(line.end.y - line.start.y, line.end.x - line.start.x);
    context.beginPath();
    context.moveTo(line.end.x, line.end.y);
    context.lineTo(line.end.x - headlen * Math.cos(angle - Math.PI / 6), line.end.y - headlen * Math.sin(angle - Math.PI / 6));
    context.lineTo(line.end.x - headlen * Math.cos(angle + Math.PI / 6), line.end.y - headlen * Math.sin(angle + Math.PI / 6));
    context.lineTo(line.end.x, line.end.y);
    context.fillStyle = '#1890ff';
    context.fill();
  })
}

// 添加节点
const addNode = (type) => {
  const node = {
    id: Date.now(),
    type,
    x: Math.random() * canvas.value.width, // 随机位置
    y: Math.random() * canvas.value.height,
    text: `节点${nodes.value.length + 1}`,
  }
  nodes.value.push(node)
  draw()
}

// 鼠标事件处理
const handleMouseDown = (e) => {
  const rect = canvas.value.getBoundingClientRect()
  const x = e.clientX - rect.left
  const y = e.clientY - rect.top

  // 查找点击的节点
  const node = nodes.value.find(n => 
    x >= n.x - 30 && x <= n.x + 30 &&
    y >= n.y - 20 && y <= n.y + 20
  )

  if (node) {
    if (mode.value === 'select') {
      if (selectedNode.value.includes(node)) {
        selectedNode.value = selectedNode.value.filter(n => n.id !== node.id);
      } else {
        selectedNode.value.push(node);
      }
      isDragging.value = true
    } else if (mode.value === 'line') {
      startNode.value = node
    }

    // 双击编辑节点文本
    canvas.value.addEventListener('dblclick', () => {
      const newText = prompt('编辑节点文本', node.text)
      if (newText) {
        node.text = newText
        draw()
      }
    })
  } else {
    selectedNode.value = [];
  }
  
  draw()
}

const handleMouseMove = (e) => {
  if (!isDragging.value || selectedNode.value.length === 0) return

  const rect = canvas.value.getBoundingClientRect()
  const x = e.clientX - rect.left
  const y = e.clientY - rect.top

  selectedNode.value.forEach(node => {
    node.x = x
    node.y = y
  });

  draw()
}

const handleMouseUp = (e) => {
  if (mode.value === 'line' && startNode.value) {
    const rect = canvas.value.getBoundingClientRect()
    const x = e.clientX - rect.left
    const y = e.clientY - rect.top

    // 查找目标节点
    const endNode = nodes.value.find(n => 
      x >= n.x - 30 && x <= n.x + 30 &&
      y >= n.y - 20 && y <= n.y + 20
    )

    if (endNode && endNode !== startNode.value) {
      lines.value.push({
        id: Date.now(),
        start: startNode.value,
        end: endNode
      })
    }

    startNode.value = null
    draw()
  }

  isDragging.value = false
}

// 清空画布
const clearCanvas = () => {
  nodes.value = []
  lines.value = []
  draw()
}

// 添加保存和加载功能
const saveCanvas = () => {
  const data = {
    nodes: nodes.value,
    lines: lines.value
  }
  localStorage.setItem('flowData', JSON.stringify(data))
}

const loadCanvas = () => {
  const data = JSON.parse(localStorage.getItem('flowData'))
  if (data) {
    nodes.value = data.nodes
    lines.value = data.lines
    draw()
  }
}

// 添加导出功能
const exportCanvas = () => {
  const data = {
    nodes: nodes.value,
    lines: lines.value
  }
  const json = JSON.stringify(data);
  const blob = new Blob([json], { type: 'application/json' });
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = 'flow.json';
  a.click();
  URL.revokeObjectURL(url);
}

// 添加导入功能
const importCanvas = (event) => {
  const file = event.target.files[0];
  const reader = new FileReader();
  reader.onload = (e) => {
    const data = JSON.parse(e.target.result);
    nodes.value = data.nodes;
    lines.value = data.lines;
    draw();
  }
  reader.readAsText(file);
}

// 添加右键菜单事件
const handleContextMenu = (e) => {
  e.preventDefault()
  const rect = canvas.value.getBoundingClientRect()
  const x = e.clientX - rect.left
  const y = e.clientY - rect.top

  const node = nodes.value.find(n => 
    x >= n.x - 30 && x <= n.x + 30 &&
    y >= n.y - 20 && y <= n.y + 20
  )

  if (node) {
    const menuOptions = confirm(`右键点击节点: ${node.text}. 是否删除该节点?`);
    if (menuOptions) {
      nodes.value = nodes.value.filter(n => n.id !== node.id);
      lines.value = lines.value.filter(line => line.start.id !== node.id && line.end.id !== node.id);
      draw();
    }
  }
}

// 添加缩放和移动画布的逻辑
const handleWheel = (e) => {
  e.preventDefault()
  scale.value += e.deltaY * -0.01
  scale.value = Math.min(Math.max(0.5, scale.value), 2) // 限制缩放范围
  draw()
}
</script>

<style scoped>
.flow-editor {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  background: #f0f2f5;
  padding: 16px;
}

.toolbar {
  margin-bottom: 16px;
}

.flow-canvas {
  flex: 1;
  background: #fff;
  border: 1px solid #d9d9d9;
  border-radius: 2px;
}
</style>